import java.util.LinkedList;

/**
 * Class holding the structure of a vehicle.
 * @author Jared Lindbl�m
 */
public class Vehicle {
	private String name;
	private Path path;
	private Intersection previousIntersection;
	private Section currentRoadSection;
	private Intersection origin, destination;
	private Direction currentDirection;
	private int speed;

	/**
	 * Constructor.
	 * @param name                  The name of the vehicle.
	 * @param origin                The origin (starting location) of the vehicle.
	 * @param destination   The destination of the vehicle.
	 */
	public Vehicle (String name, Intersection origin, Intersection destination, int speed) {
		this.name = name;
		path = new Path();
		this.origin = origin;
		this.currentRoadSection = null;
		this.destination = destination;
		this.previousIntersection = origin;
		this.currentDirection = null;
		this.speed = speed;
	}

	/**
	 * Accessor Method (Name).
	 * @return The name of the vehicle.
	 */
	public String getName() {
		return name;
	}

	/**
	 * Accessor Method (Path).
	 * @return The path of the vehicle.
	 */
	public Section[] getPath() {
		return path.getPath();
	}

	/**
	 * Accessor Method (Origin).
	 * @return The origin of the vehicle.
	 */
	public Intersection getOrigin() {
		return origin;
	}

	/**
	 * Accessor Method (Current Road).
	 * @return The road the vehicle is currently on.
	 */
	public Section getCurrentRoadSection() {
		return currentRoadSection;
	}

	/**
	 * Accessor Method (Previous Intersection).
	 * @return The intersection the vehicle last passed.
	 */
	public Intersection getPreviousIntersection() {
		return previousIntersection;
	}

	/**
	 * Accessor Method (Destination).
	 * @return The destination of the vehicle.
	 */
	public Intersection getDestination() {
		return destination;
	}

	/**
	 * Accessor Method (Speed).
	 * @return The speed of the vehicle.
	 */
	public int getSpeed() {
		return speed;
	}

	/**
	 * Set Method (Current Road).
	 * @param road  The road the vehicle is currently on.
	 */
	public boolean updateCurrentRoad(Section newRoadSection, Direction newDirection) {
		boolean success = false;
		// Can this vehicle be added to the newRoad?  If so,
		// Add it to the road.
		if(newRoadSection!=null){
			if (newRoadSection.addVehicle(this, newDirection)) {
				// Remove Vehicle from Previous Road
				if(currentRoadSection!=null)
					currentRoadSection.removeVehicle(this, currentDirection);
				
				// road -> currentRoad
				currentRoadSection = newRoadSection;
				currentDirection = newDirection;
				path.addRoadSection(currentRoadSection);
				
				success = true;
			}
		}else{
			if(currentRoadSection!=null){
				currentRoadSection.removeVehicle(this, currentDirection);
				currentRoadSection = null;
				currentDirection = null;
				success = true;
			}
				//currentRoadSection.removeVehicle(this, currentDirection);
			//else System.out.println("CurrentRaodSection null"+this.printPath());
			
		}
		
		return success;
	}

	public void updateCurrentRoadwithoutMax(Section newRoadSection, Direction newDirection) {
		
		// Add it to the road.
		if(newRoadSection!=null){
			if(currentRoadSection!=newRoadSection){
				if (newRoadSection.addVehiclewithoutMax(this, newDirection)) {
					// Remove Vehicle from Previous Road
					if(currentRoadSection!=null)
						currentRoadSection.removeVehicle(this, currentDirection);
					
					// road -> currentRoad
					currentRoadSection = newRoadSection;
					currentDirection = newDirection;
					path.addRoadSection(currentRoadSection);
				}
			}
		}else{
			if(currentRoadSection!=null){
				currentRoadSection.removeVehicle(this, currentDirection);
				currentRoadSection = null;
				currentDirection = null;
				
			}	
		}
	}
	
	/**
	 * Set Method (Previous Intersection).
	 * @param intersection The intersection the vehicle last passed.
	 */
	public void updatePreviousIntersection(Intersection intersection) {
		previousIntersection = intersection;
	}

	/**
	 * Backtrack to the last road the vehicle was on.  
	 * This will be useful of Dijkstra's Algorithm.
	 */
	public boolean backtrack(Direction previousDirection) {
		boolean success = false;
		
		// Can this vehicle be added to the previous Road? If so,
		// Add it to the road.
		
		// Pop current Road on Stack and look at Previous Road
		Section temp = path.peek();
		path.removeRoadSection();
		
		if ((path.peek()).addVehicle(this, previousDirection)) {
			// Remove Vehicle from Current Road
			currentRoadSection.removeVehicle(this, currentDirection);
			
			// previous Road -> currentRoad
			currentRoadSection = path.peek();
			currentDirection = previousDirection;
			
			success = true;
		}
		else {
			// If fail, push current road back onto stack and fail.
			path.addRoadSection(temp);
		}
		
		return success;
	}

	/**
	 * Prints out the structure of this vehicle (for debugging).
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		String print = "Name: " + name;
		print = print.concat("\n\n\t\t\tOrigination: " + origin.getName());

		if (currentRoadSection != null) {
			print = print.concat("\n\t\t\tCurrentRoad: " + currentRoadSection.getName());
		}
		else {
			print = print.concat("\n\t\t\tCurrentRoad: Currently not on a Road");
		}

		print = print.concat("\n\t\t\tDestination: " + destination.getName());
		print = print.concat("\n\t\t\tSpeed: " + speed);
		print = print.concat("\n");
		return print;
	}
	
	public LinkedList<String> printPath(){
		Section[] sections = path.getPath();
		//ArrayList<Section> pathList = new ArrayList<Section>(Arrays.asList(sections));
		LinkedList<String> pathList = new LinkedList<String>();
		for(Section section:sections){
			pathList.add(section.getDescription());
		}
		return pathList;
	}

}